Add support to domain builders for loading kernels with physical addresses in the...
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Thu, 11 May 2006 16:30:50 +0000 (17:30 +0100)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Thu, 11 May 2006 16:30:50 +0000 (17:30 +0100)
Add a new __xen_guest header field to distinguish between kernels with
the previous use of the paddr field and the new use.
Add a new __xen_guest header field to control the kernel entry point,
since the elf header entry field now points to a physical address.
This header field is also useful for supporting alternative entry
points in kernel images which run both on xen and native.
Also add a kernel config option to control whether the resulting kernel
should include compatibility code to run on Xen 3.0.2 or whether such
code such be left out, resulting in a kernel which will only run on
newer Xen versions.  Default to having compatibility enabled.
Kernels built with the new use of the elf header fields would otherwise
not work on Xen versions prior to this changeset.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
15 files changed:
buildconfigs/linux-defconfig_xen0_x86_32
buildconfigs/linux-defconfig_xen0_x86_64
buildconfigs/linux-defconfig_xenU_x86_32
buildconfigs/linux-defconfig_xenU_x86_64
buildconfigs/linux-defconfig_xen_x86_32
buildconfigs/linux-defconfig_xen_x86_64
linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S
linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S
linux-2.6-xen-sparse/drivers/xen/Kconfig
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h
tools/libxc/xc_load_elf.c
tools/libxc/xg_private.h
xen/common/elf.c
xen/include/xen/sched.h

index 4c040a58ae7f27c59b0d95cfce9b56959fa544c0..defb6d72da64db9ccbf614a08a4937d73ba8525b 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-xen0
-# Sat Apr  8 11:34:07 2006
+# Linux kernel version: 2.6.16.13-xen0
+# Thu May 11 17:06:31 2006
 #
 CONFIG_X86_32=y
 CONFIG_SEMAPHORE_SLEEPERS=y
@@ -1309,7 +1309,7 @@ CONFIG_CRYPTO_CRC32C=m
 #
 # CONFIG_CRYPTO_DEV_PADLOCK is not set
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030101
+CONFIG_XEN_INTERFACE_VERSION=0x00030202
 
 #
 # XEN
@@ -1330,10 +1330,12 @@ CONFIG_XEN_NETDEV_LOOPBACK=y
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
 # CONFIG_XEN_BLKDEV_TAP is not set
-# CONFIG_XEN_TPMDEV_FRONTEND is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
 CONFIG_HAVE_ARCH_ALLOC_SKB=y
 CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
 CONFIG_NO_IDLE_HZ=y
index 763b918e27e5c251667ee8a524c8b415026becca..dd358f589690a1dfce4f5f27db03ca4fd3701fb9 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-xen0
-# Thu Apr 13 14:58:29 2006
+# Linux kernel version: 2.6.16.13-xen0
+# Thu May 11 17:17:19 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -1250,7 +1250,7 @@ CONFIG_CRYPTO_CRC32C=m
 # Hardware crypto devices
 #
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030101
+CONFIG_XEN_INTERFACE_VERSION=0x00030202
 
 #
 # XEN
@@ -1271,10 +1271,12 @@ CONFIG_XEN_NETDEV_LOOPBACK=y
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
 # CONFIG_XEN_BLKDEV_TAP is not set
-# CONFIG_XEN_TPMDEV_FRONTEND is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
 CONFIG_HAVE_ARCH_ALLOC_SKB=y
 CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
 CONFIG_NO_IDLE_HZ=y
index 950220c07925784ae636028934c098ec5826fac6..b1cba934ef9781867c737b185abe63813166e0cd 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc3-xen0
-# Thu Feb 16 22:53:43 2006
+# Linux kernel version: 2.6.16.13-xenU
+# Thu May 11 17:08:12 2006
 #
 CONFIG_X86_32=y
 CONFIG_SEMAPHORE_SLEEPERS=y
@@ -617,11 +617,7 @@ CONFIG_DUMMY_CONSOLE=y
 #
 
 #
-# SN Devices
-#
-
-#
-# EDAC - error detection and reporting (RAS)
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 # CONFIG_EDAC is not set
 
@@ -852,7 +848,7 @@ CONFIG_CRYPTO_CRC32C=m
 #
 # CONFIG_CRYPTO_DEV_PADLOCK is not set
 CONFIG_XEN=y
-CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_INTERFACE_VERSION=0x00030202
 
 #
 # XEN
@@ -862,12 +858,15 @@ CONFIG_XEN_UNPRIVILEGED_GUEST=y
 # CONFIG_XEN_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
-# CONFIG_XEN_TPMDEV_FRONTEND is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
 CONFIG_HAVE_ARCH_ALLOC_SKB=y
 CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_NO_IDLE_HZ=y
 
 #
 # Library routines
@@ -883,4 +882,6 @@ CONFIG_GENERIC_PENDING_IRQ=y
 CONFIG_X86_SMP=y
 CONFIG_X86_BIOS_REBOOT=y
 CONFIG_X86_TRAMPOLINE=y
+CONFIG_X86_NO_TSS=y
+CONFIG_X86_NO_IDT=y
 CONFIG_KTIME_SCALAR=y
index ffa1bff0f4e5970d33b700b69a4df390817b5057..ce83a618b8edcbe3b1c5941c58d328f97b63cc0b 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-xenU
-# Thu Apr 13 14:59:16 2006
+# Linux kernel version: 2.6.16.13-xenU
+# Thu May 11 17:17:57 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -1135,7 +1135,7 @@ CONFIG_CRYPTO_CRC32C=m
 # Hardware crypto devices
 #
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030101
+CONFIG_XEN_INTERFACE_VERSION=0x00030202
 
 #
 # XEN
@@ -1145,10 +1145,12 @@ CONFIG_XEN_UNPRIVILEGED_GUEST=y
 # CONFIG_XEN_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
-# CONFIG_XEN_TPMDEV_FRONTEND is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
 CONFIG_HAVE_ARCH_ALLOC_SKB=y
 CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
 CONFIG_NO_IDLE_HZ=y
index 5ef11bc386101b25432a93aeb96a9b113674dfe8..1b7440637ac486ae64e6cfe6b7c4c025da37636c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-xen
-# Thu Apr 20 17:07:18 2006
+# Linux kernel version: 2.6.16.13-xen
+# Thu May 11 17:11:00 2006
 #
 CONFIG_X86_32=y
 CONFIG_SEMAPHORE_SLEEPERS=y
@@ -888,7 +888,7 @@ CONFIG_MTD_NAND_DISKONCHIP=m
 # CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
 CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
 CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
-CONFIG_MTD_NAND_NANDSIM=y
+CONFIG_MTD_NAND_NANDSIM=m
 
 #
 # OneNAND Flash Device Drivers
@@ -3009,7 +3009,7 @@ CONFIG_CRYPTO_TEST=m
 #
 # CONFIG_CRYPTO_DEV_PADLOCK is not set
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030101
+CONFIG_XEN_INTERFACE_VERSION=0x00030202
 
 #
 # XEN
@@ -3030,10 +3030,12 @@ CONFIG_XEN_NETDEV_LOOPBACK=y
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
 # CONFIG_XEN_BLKDEV_TAP is not set
-CONFIG_XEN_TPMDEV_FRONTEND=m
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
 CONFIG_HAVE_ARCH_ALLOC_SKB=y
 CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
 CONFIG_NO_IDLE_HZ=y
index a076efff9d6b1d8ecc688abe30df93f09a46a418..87cc8e69bb6bc2394770339114fc6abad3ba7003 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-xen
-# Thu Apr 20 17:05:48 2006
+# Linux kernel version: 2.6.16.13-xen
+# Thu May 11 17:18:58 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -840,7 +840,7 @@ CONFIG_MTD_NAND_DISKONCHIP=m
 # CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
 CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
 CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
-CONFIG_MTD_NAND_NANDSIM=y
+CONFIG_MTD_NAND_NANDSIM=m
 
 #
 # OneNAND Flash Device Drivers
@@ -2841,7 +2841,7 @@ CONFIG_CRYPTO_TEST=m
 # Hardware crypto devices
 #
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030101
+CONFIG_XEN_INTERFACE_VERSION=0x00030202
 
 #
 # XEN
@@ -2863,10 +2863,12 @@ CONFIG_XEN_TPMDEV_BACKEND=m
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
 # CONFIG_XEN_BLKDEV_TAP is not set
-CONFIG_XEN_TPMDEV_FRONTEND=m
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
 CONFIG_HAVE_ARCH_ALLOC_SKB=y
 CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
 CONFIG_NO_IDLE_HZ=y
index 23e62c054337958e748b0da06eb5f973977e4917..00ec0c2a5e157f172eb4f9d790745f222962e5ac 100644 (file)
@@ -23,6 +23,8 @@
 #define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability
 #define X86_VENDOR_ID  new_cpu_data+CPUINFO_x86_vendor_id
 
+#define VIRT_ENTRY_OFFSET 0x0
+.org VIRT_ENTRY_OFFSET
 ENTRY(startup_32)
        movl %esi,xen_start_info
        cld
@@ -155,6 +157,14 @@ ENTRY(cpu_gdt_table)
        .ascii  ",XEN_VER=xen-3.0"
        .ascii  ",VIRT_BASE=0x"
                utoa __PAGE_OFFSET
+#ifdef CONFIG_XEN_COMPAT_030002
+       .ascii  ",ELF_PADDR_OFFSET=0x"
+               utoa __PAGE_OFFSET
+#else
+       .ascii  ",ELF_PADDR_OFFSET=0x0"
+#endif /* !CONFIG_XEN_COMPAT_030002 */
+       .ascii  ",VIRT_ENTRY=0x"
+               utoa (__PAGE_OFFSET + __PHYSICAL_START + VIRT_ENTRY_OFFSET)
        .ascii  ",HYPERCALL_PAGE=0x"
                utoa ((__PHYSICAL_START+HYPERCALL_PAGE_OFFSET)>>PAGE_SHIFT)
        .ascii  ",FEATURES=writable_page_tables"
index 1f3e07bfb03a76501c63e0cf4319bae57a6d487f..11ea79f8a6a1aaa305e5b04d04c39193d8ad942c 100644 (file)
@@ -24,6 +24,8 @@
 
        .text
        .code64
+#define VIRT_ENTRY_OFFSET 0x0
+.org VIRT_ENTRY_OFFSET
        .globl startup_64
 startup_64:
 ENTRY(_start)
@@ -146,8 +148,18 @@ gdt_end:
 .section __xen_guest
        .ascii  "GUEST_OS=linux,GUEST_VER=2.6"
        .ascii  ",XEN_VER=xen-3.0"
-       .ascii  ",VIRT_BASE=0x"; utoh __START_KERNEL_map
-       .ascii  ",HYPERCALL_PAGE=0x"; utoh (phys_hypercall_page >> PAGE_SHIFT)
+       .ascii  ",VIRT_BASE=0x"
+               utoh __START_KERNEL_map
+#ifdef CONFIG_XEN_COMPAT_030002
+       .ascii  ",ELF_PADDR_OFFSET=0x"
+               utoh __START_KERNEL_map
+#else
+       .ascii  ",ELF_PADDR_OFFSET=0x0"
+#endif /* !CONFIG_XEN_COMPAT_030002 */
+       .ascii  ",VIRT_ENTRY=0x"
+               utoh (__START_KERNEL_map + __PHYSICAL_START + VIRT_ENTRY_OFFSET)
+       .ascii  ",HYPERCALL_PAGE=0x"
+               utoh (phys_hypercall_page >> PAGE_SHIFT)
        .ascii  ",FEATURES=writable_page_tables"
        .ascii           "|writable_descriptor_tables"
        .ascii           "|auto_translated_physmap"
index 45f53ab0cd2d171aabb0da37ac6bfa01c9001b74..34fe912fae803384f2afb106b4fd1a804c6dac90 100644 (file)
@@ -198,6 +198,22 @@ config XEN_SYSFS
        help
                Xen hypervisor attributes will show up under /sys/hypervisor/.
 
+choice
+       prompt "Xen version compatibility"
+       default XEN_COMPAT_030002_AND_LATER
+
+       config XEN_COMPAT_030002_AND_LATER
+               bool "3.0.2 and later"
+
+       config XEN_COMPAT_LATEST_ONLY
+               bool "no compatibility code"
+
+endchoice
+
+config XEN_COMPAT_030002
+       bool
+       default XEN_COMPAT_030002_AND_LATER
+
 endmenu
 
 config HAVE_ARCH_ALLOC_SKB
index cfdffff2586f019b01cbb32e31c4f756d1ec0946..60f1742118b7c11b189913abb4a946164ccba7cc 100644 (file)
@@ -289,9 +289,10 @@ extern int page_is_ram(unsigned long pagenr);
 #endif
 #define __KERNEL_START         (__PAGE_OFFSET + __PHYSICAL_START)
 
+#ifdef CONFIG_XEN_COMPAT_030002
 #undef LOAD_OFFSET
 #define LOAD_OFFSET            0
-
+#endif /* CONFIG_XEN_COMPAT_030002 */
 
 #define PAGE_OFFSET            ((unsigned long)__PAGE_OFFSET)
 #define VMALLOC_RESERVE                ((unsigned long)__VMALLOC_RESERVE)
index 73d9282a85b4282956ec2a0fc12c2c391c2178af..3144836406bdad2d3a52293b73e89e64c3f2a7e2 100644 (file)
@@ -260,8 +260,10 @@ static inline pgd_t __pgd(unsigned long x)
 #define __PAGE_OFFSET           0xffff880000000000
 #endif /* !__ASSEMBLY__ */
 
+#ifdef CONFIG_XEN_COMPAT_030002
 #undef LOAD_OFFSET
 #define LOAD_OFFSET            0
+#endif /* CONFIG_XEN_COMPAT_030002 */
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
index a60fd42d2aaaac5f31dc5bdea9cb29299d1b61e7..610f0a53df23e0187c9e6d5513641cdd6467d511 100644 (file)
@@ -58,7 +58,7 @@ static int parseelfimage(const char *image,
     Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
     Elf_Phdr *phdr;
     Elf_Shdr *shdr;
-    unsigned long kernstart = ~0UL, kernend=0UL;
+    unsigned long kernstart = ~0UL, kernend=0UL, vaddr, virt_base;
     const char *shstrtab;
     char *guestinfo=NULL, *p;
     int h;
@@ -148,35 +148,47 @@ static int parseelfimage(const char *image,
 
     dsi->xen_guest_string = guestinfo;
 
+    virt_base = 0;
+    if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
+        virt_base = strtoul(p+10, &p, 0);
+    dsi->elf_paddr_offset = virt_base;
+    if ( (p = strstr(guestinfo, "ELF_PADDR_OFFSET=")) != NULL )
+        dsi->elf_paddr_offset = strtoul(p+17, &p, 0);
+
     for ( h = 0; h < ehdr->e_phnum; h++ )
     {
         phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
         if ( !is_loadable_phdr(phdr) )
             continue;
-        if ( phdr->p_paddr < kernstart )
-            kernstart = phdr->p_paddr;
-        if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
-            kernend = phdr->p_paddr + phdr->p_memsz;
+        vaddr = phdr->p_paddr - dsi->elf_paddr_offset + virt_base;
+        if ( vaddr < kernstart )
+            kernstart = vaddr;
+        if ( (vaddr + phdr->p_memsz) > kernend )
+            kernend = vaddr + phdr->p_memsz;
     }
 
+    if ( virt_base )
+        dsi->v_start = virt_base;
+    else
+        dsi->v_start = kernstart;
+
+    dsi->v_kernentry = ehdr->e_entry;
+    if ( (p = strstr(guestinfo, "VIRT_ENTRY=")) != NULL )
+        dsi->v_kernentry = strtoul(p+11, &p, 0);
+
     if ( (kernstart > kernend) ||
-         (ehdr->e_entry < kernstart) ||
-         (ehdr->e_entry > kernend) )
+         (dsi->v_kernentry < kernstart) ||
+         (dsi->v_kernentry > kernend) )
     {
         ERROR("Malformed ELF image.");
         return -EINVAL;
     }
 
-    dsi->v_start = kernstart;
-    if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
-        dsi->v_start = strtoul(p+10, &p, 0);
-
     if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
         dsi->load_symtab = 1;
 
     dsi->v_kernstart = kernstart;
     dsi->v_kernend   = kernend;
-    dsi->v_kernentry = ehdr->e_entry;
     dsi->v_end       = dsi->v_kernend;
 
     loadelfsymtab(image, 0, 0, NULL, dsi);
@@ -204,7 +216,7 @@ loadelfimage(
 
         for ( done = 0; done < phdr->p_filesz; done += chunksz )
         {
-            pa = (phdr->p_paddr + done) - dsi->v_start;
+            pa = (phdr->p_paddr + done) - dsi->elf_paddr_offset;
             va = xc_map_foreign_range(
                 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
             chunksz = phdr->p_filesz - done;
@@ -217,7 +229,7 @@ loadelfimage(
 
         for ( ; done < phdr->p_memsz; done += chunksz )
         {
-            pa = (phdr->p_paddr + done) - dsi->v_start;
+            pa = (phdr->p_paddr + done) - dsi->elf_paddr_offset;
             va = xc_map_foreign_range(
                 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
             chunksz = phdr->p_memsz - done;
index f7e8efac5bb88e153424321de76835ec99f63108..4284e0f79b16711246e40d3d0506c24b38340b74 100644 (file)
@@ -136,8 +136,11 @@ struct domain_setup_info
     unsigned long v_kernend;
     unsigned long v_kernentry;
 
-    unsigned int  load_symtab;
+    unsigned long elf_paddr_offset;
+
     unsigned int  pae_kernel;
+
+    unsigned int  load_symtab;
     unsigned long symtab_addr;
     unsigned long symtab_len;
 
index 412acae01aa21c82f0004bc8226de6a57afa73ae..83155e0e08e65acd851e8118dfbeee20bce6c5de 100644 (file)
@@ -23,7 +23,7 @@ int parseelfimage(struct domain_setup_info *dsi)
     Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
     Elf_Phdr *phdr;
     Elf_Shdr *shdr;
-    unsigned long kernstart = ~0UL, kernend=0UL;
+    unsigned long kernstart = ~0UL, kernend=0UL, vaddr, virt_base;
     char *shstrtab, *guestinfo=NULL, *p;
     char *elfbase = (char *)dsi->image_addr;
     int h;
@@ -81,39 +81,50 @@ int parseelfimage(struct domain_setup_info *dsi)
 
     dsi->xen_section_string = guestinfo;
 
-    for ( h = 0; h < ehdr->e_phnum; h++ ) 
+    if ( guestinfo == NULL )
+        guestinfo = "";
+
+    virt_base = 0;
+    if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
+        virt_base = simple_strtoul(p+10, &p, 0);
+    dsi->elf_paddr_offset = virt_base;
+    if ( (p = strstr(guestinfo, "ELF_PADDR_OFFSET=")) != NULL )
+        dsi->elf_paddr_offset = simple_strtoul(p+17, &p, 0);
+
+    for ( h = 0; h < ehdr->e_phnum; h++ )
     {
         phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
         if ( !is_loadable_phdr(phdr) )
             continue;
-        if ( phdr->p_paddr < kernstart )
-            kernstart = phdr->p_paddr;
-        if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
-            kernend = phdr->p_paddr + phdr->p_memsz;
+        vaddr = phdr->p_paddr - dsi->elf_paddr_offset + virt_base;
+        if ( vaddr < kernstart )
+            kernstart = vaddr;
+        if ( (vaddr + phdr->p_memsz) > kernend )
+            kernend = vaddr + phdr->p_memsz;
     }
 
+    if ( virt_base )
+        dsi->v_start = virt_base;
+    else
+        dsi->v_start = kernstart;
+
+    dsi->v_kernentry = ehdr->e_entry;
+    if ( (p = strstr(guestinfo, "VIRT_ENTRY=")) != NULL )
+        dsi->v_kernentry = simple_strtoul(p+11, &p, 0);
+
     if ( (kernstart > kernend) || 
-         (ehdr->e_entry < kernstart) || 
-         (ehdr->e_entry > kernend) )
+         (dsi->v_kernentry < kernstart) ||
+         (dsi->v_kernentry > kernend) )
     {
         printk("Malformed ELF image.\n");
         return -EINVAL;
     }
 
-    dsi->v_start = kernstart;
-
-    if ( guestinfo != NULL )
-    {
-        if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
-            dsi->v_start = simple_strtoul(p+10, &p, 0);
-
-        if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
+    if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
             dsi->load_symtab = 1;
-    }
 
     dsi->v_kernstart = kernstart;
     dsi->v_kernend   = kernend;
-    dsi->v_kernentry = ehdr->e_entry;
     dsi->v_end       = dsi->v_kernend;
 
     loadelfsymtab(dsi, 0);
@@ -126,18 +137,19 @@ int loadelfimage(struct domain_setup_info *dsi)
     char *elfbase = (char *)dsi->image_addr;
     Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
     Elf_Phdr *phdr;
+    unsigned long vaddr;
     int h;
   
-    for ( h = 0; h < ehdr->e_phnum; h++ ) 
+    for ( h = 0; h < ehdr->e_phnum; h++ )
     {
         phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
         if ( !is_loadable_phdr(phdr) )
             continue;
+        vaddr = phdr->p_paddr - dsi->elf_paddr_offset + dsi->v_start;
         if ( phdr->p_filesz != 0 )
-            memcpy((char *)phdr->p_paddr, elfbase + phdr->p_offset, 
-                   phdr->p_filesz);
+            memcpy((char *)vaddr, elfbase + phdr->p_offset, phdr->p_filesz);
         if ( phdr->p_memsz > phdr->p_filesz )
-            memset((char *)phdr->p_paddr + phdr->p_filesz, 0, 
+            memset((char *)vaddr + phdr->p_filesz, 0,
                    phdr->p_memsz - phdr->p_filesz);
     }
 
index 178697f12ebc37d71a85df9d34c7906e6ce4a90e..0c0c31ad75dd992a688f2a371dc1dab27661eb07 100644 (file)
@@ -173,6 +173,7 @@ struct domain_setup_info
     unsigned long v_kernend;
     unsigned long v_kernentry;
     /* Initialised by loader: Private. */
+    unsigned long elf_paddr_offset;
     unsigned int  load_symtab;
     unsigned long symtab_addr;
     unsigned long symtab_len;